package SimpleLACore

import chisel3.util._
import chisel3._

class SimpleCacheReq extends Bundle {
  val wen = UInt(4.W)
  val mat = UInt(2.W)
  val addr = UInt(32.W)
  val wdata = UInt(32.W)
  val cacop = Bool()
  val code = UInt(2.W)
  val preld = Bool()
}

class SimpleCacheIO extends Bundle {
  val req = Flipped(Valid(new SimpleCacheReq))
  val resp = Valid(UInt(32.W))
}

class SimpleICacheIO extends Bundle{
  val req = Flipped(Valid(new SimpleCacheReq))//Let Chisel optimize this
  val cacop = Flipped(Valid(new SimpleCacheReq))
  val resp = Valid(UInt(32.W))
}

class SimpleCacheMeta extends Bundle with SimpleLACoreParam{
  val tag = UInt(tagBits.W)
  val valid = Bool()
  val dirty = Bool()
}

abstract class AXI4BundleA extends Bundle
{
  val id     = UInt(4.W)
  val addr   = UInt(32.W)
  val len    = UInt(8.W)
  val size   = UInt(3.W)
  val burst  = UInt(2.W)
  val lock   = UInt(2.W)
  val cache  = UInt(4.W)
  val prot   = UInt(3.W)
}

class AXI4BundleAW extends AXI4BundleA

class AXI4BundleAR extends AXI4BundleA

class AXI4BundleW extends Bundle
{
  val id   = UInt(4.W)
  val data = UInt(32.W)
  val strb = UInt(4.W)
  val last = Bool()
}

class AXI4BundleR extends Bundle
{
  val id   = UInt(4.W)
  val data = UInt(32.W)
  val resp = UInt(2.W)
  val last = Bool()
}

class AXI4BundleB extends Bundle
{
  val id   = UInt(4.W)
  val resp = UInt(2.W)
}

class AXI4Bundle extends Bundle
{
  val aw = Irrevocable(new AXI4BundleAW)
  val w  = Irrevocable(new AXI4BundleW )
  val b  = Flipped(Irrevocable(new AXI4BundleB ))
  val ar = Irrevocable(new AXI4BundleAR)
  val r  = Flipped(Irrevocable(new AXI4BundleR ))
}

class SRAMIO extends Bundle {
  val req     = Input(Bool())
  val wr      = Input(Bool())
  val size    = Input(UInt(2.W))
  val addr    = Input(UInt(32.W))
  val wstrb   = Input(UInt(4.W))
  val wdata   = Input(UInt(32.W))
  val addr_ok = Output(Bool())
  val data_ok = Output(Bool())
  val rdata   = Output(UInt(32.W))
  def req_fire: Bool= req && addr_ok
  def rBytes  = rdata.asTypeOf(Vec(4, UInt(8.W)))
}

object toBytes{
  def apply(data: UInt): Vec[UInt] = {
    require(data.getWidth == 32)
    data.asTypeOf(Vec(4, UInt(8.W)))
  }
}
